﻿using System;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using YJKDimensionModel.LevelDimension;
using YJKRevitCode.ElmentSearchUtility.LinkDocumentSuite;
using YJKRevitCode.RevitDimensionUtility;
using YJKRGeometry;
using YJKRGeometry.CurveUtility;
using SectionSignAndFilled.StairsRoomPlanSign;
using SectionSignAndFilled.StairsRoomSection.DataDefine;
using SectionSignAndFilled.StairsRoomSection.Kit.Xdata;

namespace SectionSignAndFilled.StairsRoomSection.Kit
{
	internal class SignCommon
	{
		public static double TransformDouble(Transform transform, double dVal)
		{
			XYZ xyz = new XYZ(0.0, 0.0, dVal);
			XYZ xyz2 = transform.OfPoint(xyz);
			return xyz2.Z;
		}

		public static Curve ChangeLineElevator(Curve crv, double dblElevator)
		{
			XYZ endPoint = crv.GetEndPoint(0);
			double num = dblElevator - endPoint.Z;
			Transform transform = Transform.CreateTranslation(XYZ.BasisZ * num);
			return crv.CreateTransformed(transform) as Line;
		}

		public static Curve GetGridCurveOnView(BaseLinkDocumentResultBean bean, SectionViewData viewData)
		{
			Grid grid = bean.UseElement as Grid;
			if (bean.LinkeInstanceId != -1)
			{
				return null;
			}
			return SignCommon.GetGridCurveOnView(viewData.SectionView.Document, grid.Id, null);
		}

		public static Curve GetGridCurveOnView(Autodesk.Revit.DB.Document doc, ElementId GridId, View view = null)
		{
			if (view == null)
			{
				view = doc.ActiveView;
			}
			Grid grid = doc.GetElement(GridId) as Grid;
			if (!grid.CanBeVisibleInView(view))
			{
				return null;
			}
            IList<Curve> curvesInView = grid.GetCurvesInView((DatumExtentType)1, view);
			if (curvesInView.Count == 0)
			{
				return null;
			}
			return curvesInView.First<Curve>();
		}

		public static bool CheckIntersection(List<Curve> lstCrv, Line line)
		{
			IntersectionResultArray intersectionResultArray = null;
			foreach (Curve curve in lstCrv)
			{
				line.Intersect(curve, out intersectionResultArray);
				if (intersectionResultArray != null)
				{
					return true;
				}
			}
			int num = Geometry.PointInPloygon(lstCrv, line.GetEndPoint(0));
			return num != -1;
		}

		public static void GetIntersection(List<Curve> lstCrv, Line line, List<XYZ> lstIntersecPt)
		{
			IntersectionResultArray intersectionResultArray = null;
			foreach (Curve curve in lstCrv)
			{
				line.Intersect(curve, out intersectionResultArray);
				if (intersectionResultArray != null)
				{
					foreach (object obj in intersectionResultArray)
					{
						IntersectionResult intersectionResult = (IntersectionResult)obj;
						lstIntersecPt.Add(intersectionResult.XYZPoint);
					}
				}
			}
		}

		public static bool GetWindowOrDoorSignDirAndLine(Autodesk.Revit.DB.Document doc, BaseLinkDocumentResultBean bean, Line SecLine, ref Line BaseLine, ref XYZ baseNormal)
		{
			XYZ xyz = null;
			Transform totalTransform = bean.GetTotalTransform();
			Wall wall = (bean.UseElement as FamilyInstance).Host as Wall;
			if (!SignCommon.GetWallLocationIntersectionSeclinePt(totalTransform, wall, SecLine, ref xyz))
			{
				return false;
			}
			XYZ orientation = wall.Orientation;
			XYZ xyz2 = orientation.Normalize().Negate();
			Transform totalTransform2 = bean.GetTotalTransform();
			baseNormal = totalTransform2.OfVector(xyz2);
			XYZ xyz3 = xyz + xyz2 * wall.Width / 2.0;
			xyz3 += SignCommon.m_dBaseLineInterval * baseNormal;
			BaseLine = Line.CreateUnbound(xyz3, doc.ActiveView.UpDirection);
			return true;
		}

		public static bool GetWallLocationIntersectionSeclinePt(Transform linkTrans, Wall wall, Line SecLine, ref XYZ pt)
		{
			Curve curve = (wall.Location as LocationCurve).Curve;
			Curve curve2 = curve.CreateTransformed(linkTrans);
			double num = SecLine.GetEndPoint(0).Z - curve2.GetEndPoint(0).Z;
			Transform transform = Transform.CreateTranslation(new XYZ(0.0, 0.0, num));
			Curve curve3 = curve2.CreateTransformed(transform);
			IntersectionResultArray intersectionResultArray = null;
			curve3.Intersect(SecLine, out intersectionResultArray);
			if (intersectionResultArray == null || intersectionResultArray.Size == 0)
			{
				return false;
			}
			pt = intersectionResultArray.get_Item(0).XYZPoint;
			return true;
		}

		public static bool GetPtProjectPlan(Plane plan, XYZ pt, ref XYZ ptProject)
		{
			XYZ xvec = plan.XVec;
			XYZ yvec = plan.YVec;
			XYZ origin = plan.Origin;
			Line line = Line.CreateUnbound(origin, xvec);
			IntersectionResult intersectionResult = line.Project(pt);
			if (intersectionResult == null)
			{
				return false;
			}
			XYZ xyzpoint = intersectionResult.XYZPoint;
			Line line2 = Line.CreateUnbound(xyzpoint, yvec);
			intersectionResult = line2.Project(pt);
			if (intersectionResult == null)
			{
				return false;
			}
			ptProject = intersectionResult.XYZPoint;
			return true;
		}

		public static ElementId GetDimSymbol(Autodesk.Revit.DB.Document doc)
		{
			DimensionType dimensionType = RevitDimensionUtiltyMethod.GetDimensionType(doc, DimensionTypeEnum.ScaleDimension, null);
			if (dimensionType != null)
			{
				return dimensionType.Id;
			}
			return ElementId.InvalidElementId;
		}

		public static bool CreateElevatorDim(LevelDimensionManager DimManager, Document doc, XYZ landPos, double LandingBaseElev, Dictionary<string, double> DicLayerInfo)
		{
			Plane plan = RevitVersionFuncs.CreatePlanByOriginAndBasis(doc.ActiveView.Origin, doc.ActiveView.RightDirection, doc.ActiveView.UpDirection);
			XYZ zero = XYZ.Zero;
			if (!SignCommon.GetPtProjectPlan(plan, landPos, ref zero))
			{
				return false;
			}
			FamilyInstance familyInstance = DimManager.CreateSymbolFamily(zero, doc.ActiveView, null, LandingBaseElev, true, "符号_普通标高(左上).rfa");
			SignXdataForReference.WriteSignComment(familyInstance, doc.ActiveView.Id);
			doc.Regenerate();
			string text = string.Empty;
			foreach (KeyValuePair<string, double> keyValuePair in DicLayerInfo)
			{
				if (Geometry.IsEqual(keyValuePair.Value, LandingBaseElev))
				{
					text = keyValuePair.Key;
				}
			}
			if (!text.IsEmpty<char>())
			{
				string text2 = string.Empty;
				Parameter parameter = familyInstance.GetParameters("标高1").Single<Parameter>();
				if (parameter != null && !parameter.IsReadOnly)
				{
					text2 = parameter.AsString();
					text2 = text2 + "(" + text + ")";
					parameter.Set(text2);
				}
			}
			XYZ viewDirection = doc.ActiveView.ViewDirection;
			XYZ facingOrientation = familyInstance.FacingOrientation;
			Plane plane = RevitVersionFuncs.CreatePlanByNormalAndOrigin(doc.ActiveView.UpDirection, zero);
			if (facingOrientation.Z < 0.0)
			{
				ElementTransformUtils.MirrorElement(doc, familyInstance.Id, plane);
				doc.Delete(familyInstance.Id);
			}
			return true;
		}

		public static Dimension CreateDimByElevatorAndLine(Autodesk.Revit.DB.Document doc, List<double> lstdElev, Line BaseLine, XYZ BaseNoraml)
		{
			XYZ xyz = BaseLine.Origin + 0.01 * BaseNoraml.Negate();
			ReferenceArray referenceArray = new ReferenceArray();
			foreach (double num in lstdElev)
			{
				double num2 = num;
				XYZ xyz2 = new XYZ(xyz.X, xyz.Y, num2);
				XYZ xyz3 = xyz2 + 0.02 * BaseNoraml.Negate();
				Line line = Line.CreateBound(xyz2, xyz3);
				DetailCurve detailCurve = doc.Create.NewDetailCurve(doc.ActiveView, line);
				doc.Regenerate();
				if (detailCurve != null)
				{
					SignXdataForReference.WriteSignComment(detailCurve, doc.ActiveView.Id);
				}
				Reference reference = new Reference(detailCurve);
				referenceArray.Append(reference);
			}
			ElementId dimSymbol = SignCommon.GetDimSymbol(doc);
			Dimension dimension = doc.Create.NewDimension(doc.ActiveView, BaseLine, referenceArray, doc.GetElement(dimSymbol) as DimensionType);
			if (dimension != null)
			{
				SignXdataForReference.WriteSignComment(dimension, doc.ActiveView.Id);
			}
			return dimension;
		}

		public static bool GetTopElevatorByFloor(XYZ insertPt, Dictionary<double, List<BaseLinkDocumentResultBean>> DicFloor2Elevator, Line SecLine, ref double dTopElevator)
		{
			Line line = Line.CreateUnbound(SecLine.GetEndPoint(0), SecLine.Direction);
			XYZ xyzpoint = line.Project(insertPt).XYZPoint;
			line = Line.CreateUnbound(xyzpoint, XYZ.BasisZ);
			foreach (KeyValuePair<double, List<BaseLinkDocumentResultBean>> keyValuePair in DicFloor2Elevator)
			{
				double key = keyValuePair.Key;
				if (!Geometry.LessThan(key, insertPt.Z) && !Geometry.IsEqual(key, insertPt.Z, 0.1))
				{
					foreach (BaseLinkDocumentResultBean baseLinkDocumentResultBean in keyValuePair.Value)
					{
						if (baseLinkDocumentResultBean.UseElement is Floor)
						{
							List<Face> list = new List<Face>();
							CommonFun.FindFaceInNormal(ref list, -XYZ.BasisZ, baseLinkDocumentResultBean.UseElement);
							if (list.Count == 0)
							{
								continue;
							}
							Curve curve = line.CreateTransformed(baseLinkDocumentResultBean.GetTotalTransform().Inverse);
							using (List<Face>.Enumerator enumerator3 = list.GetEnumerator())
							{
								while (enumerator3.MoveNext())
								{
									Face face = enumerator3.Current;
									IntersectionResultArray intersectionResultArray = null;
									face.Intersect(curve, out intersectionResultArray);
									if (intersectionResultArray != null && intersectionResultArray.Size != 0 && face.IsInside(intersectionResultArray.get_Item(0).UVPoint))
									{
										dTopElevator = key;
										return true;
									}
								}
								continue;
							}
						}
						bool flag = SignCommon.CheckIfIntersectionByLanding(baseLinkDocumentResultBean, xyzpoint, key, ref dTopElevator);
						if (flag)
						{
							return true;
						}
					}
				}
			}
			return false;
		}

		public static bool CheckIfIntersectionByLanding(BaseLinkDocumentResultBean bean, XYZ insertPt, double dFloorValue, ref double dTopElevator)
		{
			Stairs stairs = bean.UseElement as Stairs;
			Document document = stairs.Document;
			Transform totalTransform = bean.GetTotalTransform();
			double baseElevation = stairs.BaseElevation;
			List<ElementId> list = stairs.GetStairsLandings() as List<ElementId>;
			foreach (ElementId elementId in list)
			{
				StairsLanding stairsLanding = document.GetElement(elementId) as StairsLanding;
				double num = baseElevation + stairsLanding.BaseElevation;
				num = SignCommon.TransformDouble(totalTransform, num);
				if (Geometry.IsEqual(num, dFloorValue, 0.0001))
				{
					CurveLoop footprintBoundary = stairsLanding.GetFootprintBoundary();
					List<Curve> area = new List<Curve>(footprintBoundary);
					XYZ pt = new XYZ(insertPt.X, insertPt.Y, num);
					dTopElevator = num - stairsLanding.Thickness;
					return CurveUtility.IsPointInArea(area, pt);
				}
			}
			return false;
		}

		public static double m_dFirstBaseLineInterval = Utility.MMToFeet(600.0, true);

		public static double m_dBaseLineInterval = Utility.MMToFeet(400.0, true);
	}
}
